package com.lp.serialportlp

import java.util.Locale


object CRCUtils {
  /**
   * 计算 CRC16 Modbus 校验码
   *
   * @param data 需要计算校验码的数据字节数组
   * @return 2字节的CRC校验码，低位在前，高位在后
   */
  fun calculateCRC(data: ByteArray): ByteArray {
    var crc = 0xFFFF // 初始值

    for (b in data) {
      crc = crc xor (b.toInt() and 0xFF) // XOR 字节到 CRC 的低位

      for (i in 0..7) {
        if ((crc and 0x0001) != 0) { // 如果最低位是1
          crc = crc shr 1 // 右移一位
          crc = crc xor 0xA001 // 与多项式异或
        } else {
          crc = crc shr 1 // 直接右移一位
        }
      }
    }

    // 转换为低位在前，高位在后的字节数组
    return byteArrayOf(
      (crc and 0xFF).toByte(),  // 低位字节
      ((crc shr 8) and 0xFF).toByte() // 高位字节
    )
  }


  /*异或和校验*/
  fun Slot_GetChk(bufData: ByteArray, buflen: Int): Int {
    var crc: Byte = 0
    for (i in 0 until buflen) {
      crc = (crc + bufData[i]).toByte()
    }
    return (crc.toInt() and 0xff)
  }

  /*异或校验*/
  fun xorComputeResult(byteResult: ByteArray): String? {
    for (i in 1 until byteResult.size) {
      byteResult[i] = (byteResult[i].toInt() xor byteResult[i - 1].toInt()).toByte()
      if (i == byteResult.size - 1) {
        return Byte2Hex(
          byteResult[i]
        )
      }
    }
    return null
  }

  fun Byte2Hex(inByte: Byte?): String {
    return String.format("%02x", inByte).uppercase(Locale.getDefault())
  }


  /**
   * 将字节数组转换为十六进制字符串表示
   *
   * @param bytes 字节数组
   * @return 十六进制字符串
   */
  fun bytesToHex(bytes: ByteArray): String {
    val sb = StringBuilder()
    for (b in bytes) {
      sb.append(String.format("%02X ", b))
    }
    return sb.toString().trim { it <= ' ' }
  }
}
